package com.linkhub.oms.admin.modules.logistic.service.impl;

import com.linkhub.oms.admin.common.exception.ExceptionFactory;
import com.linkhub.oms.admin.common.util.I18nMessageUtil;
import com.linkhub.oms.admin.modules.logistic.domain.param.*;
import com.linkhub.oms.admin.modules.logistic.domain.vo.LogisticUrlDetailVO;
import com.linkhub.oms.admin.modules.logistic.domain.vo.LogisticVO;
import com.linkhub.oms.admin.modules.logistic.service.LogisticBizService;
import com.linkhub.oms.common.constant.ShopifyConstant;
import com.linkhub.oms.common.enums.IEnumConvert;
import com.linkhub.oms.common.enums.logistic.LogisticEditStatusEnum;
import com.linkhub.oms.common.exception.BizException;
import com.linkhub.oms.common.util.CacheKeyAssist;
import com.linkhub.oms.common.util.QtBeanUtil;
import com.linkhub.oms.component.redis.locker.DistributedLocker;
import com.linkhub.oms.dao.mpservice.ILogisticService;
import com.linkhub.oms.dao.mpservice.IOrderService;
import com.linkhub.oms.dao.mpservice.IShopService;
import com.linkhub.oms.dao.mpservice.IThirdPartyLogisticsUrlService;
import com.linkhub.oms.entity.LogisticEntity;
import com.linkhub.oms.entity.OrderEntity;
import com.linkhub.oms.entity.ShopEntity;
import com.linkhub.oms.entity.ThirdPartyLogisticsUrlEntity;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.List;

/**
 * @author Jaycle
 * @version 1.0.0
 * @Description LogisticBizServiceImpl.java
 * @createTime 2024/04/29 23:01
 */
@Slf4j
@Service
public class LogisticBizServiceImpl implements LogisticBizService {

    @Resource
    private ILogisticService logisticService;

    @Resource
    private IShopService shopService;

    @Resource
    private IThirdPartyLogisticsUrlService thirdPartyLogisticsUrlService;

    @Resource
    private DistributedLocker distributedLocker;

    @Resource
    private IOrderService orderService;

    /**
     * 查询物流渠道列表
     *
     * @param logisticQueryParam logisticQueryParam
     * @return logistics
     */
    @Override
    public List<LogisticVO> queryLogistics( LogisticQueryParam logisticQueryParam ) {
        List<LogisticEntity> logisticEntityList = logisticService.listLogistics(logisticQueryParam.getChannelState(), logisticQueryParam.getKeyWord());
        List<LogisticVO> logisticVOS = QtBeanUtil.copyList(logisticEntityList, LogisticVO::new, ( source, target ) -> {
            // 获取枚举值的 type 值，并设置到目标对象的 channelState 属性中
            target.setChannelState(source.getChannelState().getCode());
        });
        return logisticVOS;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void editLogisticsStatus( LogisticEditStatusParam logisticEditStatusParam ) {
        Integer authorization = logisticEditStatusParam.getChannelState();
        String channelCode = logisticEditStatusParam.getChannelCode();

        // 加锁
        String lockKey = CacheKeyAssist.getLogisticStatusEditLockKey(channelCode);
        if (!distributedLocker.tryLock(lockKey)) {
            throw ExceptionFactory.getI18nBizException("logistic.status.edit.problem");
        }

        try {
            LogisticEditStatusEnum logisticEditStatusEnum = IEnumConvert.valueOf(authorization, LogisticEditStatusEnum.class);
            if (logisticEditStatusEnum.equals(LogisticEditStatusEnum.ENABLE)) {
                // 启用渠道逻辑
                logisticService.enableLogistic(channelCode);
            } else if (logisticEditStatusEnum.equals(LogisticEditStatusEnum.DISABLE)) {
                // 停用渠道逻辑
                String startDateString = logisticEditStatusParam.getStartDate();
                String endDateString = logisticEditStatusParam.getEndDate();
                // 开始日期不能为空
                if (StringUtils.isBlank(startDateString)) {
                    throw ExceptionFactory.getI18nBizException("validation.logistic.startDate.notNull");
                }
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
                LocalDate startDate = LocalDate.parse(startDateString, formatter);
                LocalDate endDate = StringUtils.isBlank(endDateString) ? null : LocalDate.parse(endDateString, formatter);
                LocalDate nowDate = LocalDate.now(ZoneId.of("Asia/Shanghai"));

                // 结束停用日期必须大于开始停用日期和当前日期
                if (endDate != null && (endDate.compareTo(startDate) <= 0 || endDate.compareTo(nowDate) <= 0)) {
                    throw ExceptionFactory.getI18nBizException("validation.logistic.endDate.before.startDate");
                }
                // 检查当前日期是否在停用时间内，是则设置渠道状态为停用，否则仍设置为启用
                if (nowDate.compareTo(startDate) >= 0 && (endDate == null || nowDate.compareTo(endDate) < 0)) {
                    logisticEditStatusEnum = LogisticEditStatusEnum.DISABLE;
                } else {
                    logisticEditStatusEnum = LogisticEditStatusEnum.ENABLE;
                }
                logisticService.disableLogistic(channelCode, logisticEditStatusEnum, startDate, endDate);
            }
        }finally {
            distributedLocker.unlock(lockKey);
        }
    }

    @Override
    public void setLogisticUrl( LogisticUrlEditParam logisticUrlEditParam ) {
        String userId = logisticUrlEditParam.getUserId();
        Integer transportType = logisticUrlEditParam.getTransportType();
        String queryUrl = logisticUrlEditParam.getQueryUrl();
        String sysShopId = logisticUrlEditParam.getSysShopId();
        // 加锁
        String lockKey = CacheKeyAssist.getLogisticThirdPartUrlEditLockKey(sysShopId);
        if (!distributedLocker.tryLock(lockKey)) {
            throw ExceptionFactory.getI18nBizException("logistic.third.part.url.edit.problem");
        }

        try {
            if (!queryUrl.contains(ShopifyConstant.TRACK_NUMBER)) {
                throw new BizException(I18nMessageUtil.getMessage("logistic.third.part.url.pattern.problem", ShopifyConstant.TRACK_NUMBER));
            }

            thirdPartyLogisticsUrlService.saveOrUpdateLogisticUrl(userId, sysShopId, transportType, queryUrl);
        }finally {
            distributedLocker.unlock(lockKey);
        }

    }

    @Override
    public LogisticUrlDetailVO queryLogisticUrlDetail( LogisticUrlQueryParam logisticUrlQueryParam ) {
        String userId = logisticUrlQueryParam.getUserId();
        String sysShopId = logisticUrlQueryParam.getSysShopId();
        ThirdPartyLogisticsUrlEntity thirdPartyLogisticsUrlEntity = thirdPartyLogisticsUrlService.queryById(sysShopId);
        ShopEntity userShop = shopService.getUserShop(userId, sysShopId);
        if (userShop == null) {
            throw ExceptionFactory.getI18nBizException("shop.absent.error");
        }
        LogisticUrlDetailVO logisticUrlDetailVO = new LogisticUrlDetailVO();
        QtBeanUtil.copyProperties(thirdPartyLogisticsUrlEntity, logisticUrlDetailVO);
        logisticUrlDetailVO.setShopName(userShop.getShopName());

        return logisticUrlDetailVO;
    }

    @Override
    public String queryLogisticsTracking( LogisticsTrackingQueryParam logisticsTrackingQueryParam ) {
        // 查询系统订单ID对应的运单号
        OrderEntity orderEntity = orderService.getByOrderId(logisticsTrackingQueryParam.getSysOrderId());
        String waybillNumber = null;
        if (orderEntity != null) {
            waybillNumber = orderEntity.getWayBillNumber();
        }
        if (StringUtils.isBlank(waybillNumber)) {
            throw ExceptionFactory.getI18nBizException("logistic.order.no.waybill.number");
        }

        // 拼接物流查询网址返回
        return ShopifyConstant.LOGISTICS_TRACKING_URL.replace(ShopifyConstant.TRACK_NUMBER, waybillNumber);
    }
}
